[6.2][Concurrency] Fix races/overflows in TaskGroup implementation. #81815
+195
−107
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Cherry-pick #81814 to
release/6.2
.Explanation: This fixes several bugs in the implementation of task groups involving race conditions and overflows. We add loops around compare-and-swap operations and use the correct return type for discarding task groups.
Scope: Affects Swift Concurrency code that creates and cancels task groups.
Issue: rdar://151663730
Risk: Medium, this this makes quite a few changes to delicate concurrent code in the task group implementation. I'm confident the risk is worth the reward but there is more room for error here than usual.
Testing: Added tests that make the un-fixed code crash and verify that the new code does not crash. Other existing tests cover TaskGroup functionality to ensure we didn't regress anything.
Reviewer: @ktoso
statusCompletePendingReadyWaiting(), offer(), and poll() did a one-off compare_exchange_strong which could fail if the group was concurrently cancelled. Put these into loops so that they are retried when needed.
DiscardingTaskGroup creation passed the group result type as the task result type. waitAll() would then use the group result type when collecting task results. Since the task result type is always Void in this case, this would overflow the result buffer if the group result type was larger. This often works as it writes into the free space of the task allocator, but can crash if it happens to be at the end of a page or the group result type is particularly large.
rdar://151663730